/**
 * Copyright (c) 2016-2019, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.module.article.controller.api;

import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;
import io.jboot.db.model.Columns;
import io.jboot.utils.StrUtils;
import io.jboot.web.controller.annotation.RequestMapping;
import io.jpress.commons.utils.CommonsUtils;
import io.jpress.model.User;
import io.jpress.module.article.kit.ArticleKit;
import io.jpress.module.article.model.*;
import io.jpress.module.article.service.*;
import io.jpress.service.OptionService;
import io.jpress.service.UserService;
import io.jpress.web.base.ApiControllerBase;
import org.apache.commons.lang3.time.DateFormatUtils;

import javax.inject.Inject;
import java.util.Date;
import java.util.List;

/**
 * @author Michael Yang 杨福海 （fuhai999@gmail.com）
 * @version V1.0
 * @Title: 文章前台页面Controller
 * @Package io.jpress.module.article.admin
 */
@RequestMapping("/api/article")
public class ArticleApiController extends ApiControllerBase {

    @Inject
    private ArticleService articleService;

    @Inject
    private ArticleCategoryService categoryService;

    @Inject
    private OptionService optionService;

    @Inject
    private ArticleCommentService commentService;

    @Inject
    private ArticleGoodsService articleGoodsService;

    @Inject
    private UserService userService;

    @Inject
    private ArticleLikeService articleLikeService;

    @Inject
    private BannerService bannerService;

    @Inject
    private UserSignLogService userSignLogService;

    /**
     * 文章详情的api
     * 可以传 id 获取文章详情，也可以通过 slug 来获取文章详情
     * 例如：
     * http://127.0.0.1:8080/api/article?id=123
     * 或者
     * http://127.0.0.1:8080/api/article?slug=myslug
     */
    public void index() {
        Long id = getParaToLong("id");
        if (id != null) {
            Article article = articleService.findById(id);
            userService.join(article,"user_id");
            //记录当前浏览量
            articleService.doIncArticleViewCount(id);
            List<ArticleGoods> articleGoods = articleGoodsService.findByArticleId(id);
            //查询是否点赞
            boolean isLike = false;
            User user = getLoginedUser();
            if (user != null) {
                ArticleLike articleLike = articleLikeService.find(id,user.getId());
                if(articleLike != null){
                    isLike = true;
                }
            }
            List<ArticleCategory> categories = categoryService.findListByArticleId(id);
            renderJson(Ret.ok("article", article).set("articleGoods",articleGoods).set("isLike",isLike).set("categories",categories));
            return;
        }

        String slug = getPara("slug");
        if (slug != null) {
            Article article = articleService.findFirstBySlug(slug);
            renderJson(Ret.ok("article", article));
            return;
        }

        renderFailJson();
    }

    /**
     * 获取文章的分类
     */
    public void categories() {
        List<ArticleCategory> categories = categoryService.findAll();
        renderJson(Ret.ok("categories", categories));
    }


    /**
     * 获取分类详情的API
     * <p>
     * 可以通过 id 获取文章分类，也可以通过 type + slug 定位到分类
     * 分类可能是后台对应的分类，有可以是一个tag（tag也是一种分类）
     * <p>
     * 例如：
     * http://127.0.0.1:8080/api/article/category?id=123
     * 或者
     * http://127.0.0.1:8080/api/article/category?type=category&slug=myslug
     * http://127.0.0.1:8080/api/article/category?type=tag&slug=myslug
     */
    public void category() {
        Long id = getParaToLong("id");
        if (id != null) {
            ArticleCategory category = categoryService.findById(id);
            renderJson(Ret.ok("category", category));
            return;
        }

        String slug = getPara("slug");
        String type = getPara("type");

        if (StrUtils.isBlank(slug)
                || StrUtils.isBlank(type)) {
            renderFailJson();
            return;
        }


        ArticleCategory category = categoryService.findFirstByTypeAndSlug(type, slug);
        renderJson(Ret.ok("category", category));
    }


    /**
     * 通过 分类ID 分页读取文章列表
     */
    public void paginate() {
        Long categoryId = getParaToLong("categoryId");
        String orderBy = getPara("orderBy");
        String key = getPara("keyword");
        int pageNumber = getParaToInt("page", 1);

        Page<Article> page = categoryId == null
                ? articleService.paginateInNormal(pageNumber, 10, orderBy,key)
                : articleService.paginateByCategoryIdInNormal(pageNumber, 10, categoryId, orderBy,key);

        renderJson(Ret.ok().set("page", page));
    }


    /**
     * 通过 文章属性 获得文章列表
     */
    public void list() {
        String flag = getPara("flag");
        Boolean hasThumbnail = getParaToBoolean("hasThumbnail");
        String orderBy = getPara("orderBy", "id desc");
        int count = getParaToInt("count", 10);


        Columns columns = Columns.create("flag", flag);
        if (hasThumbnail != null) {
            if (hasThumbnail) {
                columns.is_not_null("thumbnail");
            } else {
                columns.is_null("thumbnail");
            }
        }

        List<Article> articles = articleService.findListByColumns(columns, orderBy, count);
        renderJson(Ret.ok("articles", articles));
    }

    /**
     * 某一篇文章的相关文章
     */
    public void relevantList() {

        Long id = getParaToLong("articleId");
        if (id == null) {
            renderFailJson();
        }

        int count = getParaToInt("count", 3);

        List<Article> relevantArticles = articleService.findRelevantListByArticleId(id, Article.STATUS_NORMAL, count);
        renderOk("articles", relevantArticles);
    }


    public void save() {
        Article article = getRawObject(Article.class);
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        //判断用户是否被冻结
        user = userService.findById(user.getId());
        if(!user.isStatusOk()){
            renderFailJson(1, "您的账号已被冻结!");
            return;
        }

        article.setUserId(user.getId());
        Boolean articleCheckEnable = optionService.findAsBoolByKey("article_check_enable");
        //需要审核
        if(articleCheckEnable != null && articleCheckEnable == true){
            article.setStatus(Article.STATUS_DRAFT);
        }else {
            article.setStatus(Article.STATUS_NORMAL);
        }
        article.setEditMode("json");
        long id = articleService.doGetIdBySaveOrUpdateAction(article);

        Long[] categoryIds = getParaValuesToLong("category");
        Long[] goodsIds = getParaValuesToLong("goods");

        articleService.doUpdateCategorys(id, categoryIds);
        articleGoodsService.linkArticleGoods(id,goodsIds);

        renderJson(Ret.ok());
    }


    public void userArticles(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        int pageNumber = getParaToInt("page", 1);
        Page<Article> page = articleService._paginateByUserId(pageNumber,10,user.getId());
        renderJson(Ret.ok().set("page", page));
    }

    public void deleteArticle(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        //判断用户是否被冻结
        user = userService.findById(user.getId());
        if(!user.isStatusOk()){
            renderFailJson(1, "您的账号已被冻结!");
            return;
        }
        Long articleId = getParaToLong("articleId");
        Article article = articleService.findById(articleId);
        if(article == null){
            renderFailJson("文章不存在");
            return;
        }
        article.setStatus(Article.STATUS_TRASH);
        articleService.update(article);
        renderOk();
    }

    public void like(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        //判断用户是否被冻结
        user = userService.findById(user.getId());
        if(!user.isStatusOk()){
            renderFailJson(1, "您的账号已被冻结!");
            return;
        }

        Long articleId = getParaToLong("articleId");
        Long userId = user.getId();

        ArticleLike articleLike = articleLikeService.find(articleId,userId);
        if(articleLike != null){
            renderFailJson("您已点过赞！");
            return;
        }
        articleLike = new ArticleLike();
        articleLike.setArticleId(articleId);
        articleLike.setUserId(userId);
        articleLikeService.save(articleLike);
        articleService.doIncArticleLikeCount(articleId);
        renderOk();
    }

    public void commentPaginate() {
        Long articleId = getParaToLong("articleId");
        int pageNumber = getParaToInt("page", 1);

        Page<ArticleComment> page = commentService.paginateByArticleIdInNormal(pageNumber, 10, articleId);
        renderJson(Ret.ok().set("page", page));
    }

    /**
     * 收到的评论
     */
    public void meCommentReceivePaginate(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        int pageNumber = getParaToInt("page",1);

        Page<ArticleComment> page = commentService.paginateCommentsReceive(pageNumber,10,user.getId());
        renderJson(Ret.ok().set("page", page));
    }

    public void commentReply(){
        User user = getLoginedUser();
        String content = getPara("content");
        Long articleId = getParaToLong("articleId");
        Long pid = getParaToLong("pid");

        ArticleComment comment = commentService.findByPid(pid);
        if(comment == null){
            comment = new ArticleComment();
            comment.setAuthor(user.getNickname());
            comment.setContent(content);
            comment.setUserId(user.getId());
            comment.setStatus(ArticleComment.STATUS_NORMAL);
            comment.setArticleId(articleId);
            comment.setPid(pid);
            commentService.save(comment);
        }else {
            comment.setContent(content);
            commentService.update(comment);
        }
        renderOk();
    }

    /**
     * 收到的回复
     */
    public void myCommentReplyPaginate(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        int pageNumber = getParaToInt("page",1);

        Page<ArticleComment> page = commentService.commentReplyPaginate(pageNumber,10,user.getId());
        renderJson(Ret.ok().set("page", page));
    }


    /**
     * 发出的评论
     */
    public void meCommentSendPaginate(){
        User user = getLoginedUser();
        if (user == null) {
            renderFailJson(1, "user not logined");
            return;
        }
        int pageNumber = getParaToInt("page",1);

        Page<ArticleComment> page = commentService.paginateCommentsSend(pageNumber,10,user.getId());
        renderJson(Ret.ok().set("page", page));
    }


    /**
     * 发布评论
     */
    public void postComment() {
        Long articleId = getParaToLong("articleId");
        Long pid = getParaToLong("pid");
        String content = getRawData();

        if (articleId == null || articleId <= 0) {
            renderJson(Ret.fail());
            return;
        }

        if (StrUtils.isBlank(content)) {
            renderJson(Ret.fail().set("message", "评论内容不能为空"));
            return;
        } else {
            content = CommonsUtils.escapeHtml(content);
        }


        Article article = articleService.findById(articleId);
        if (article == null) {
            renderJson(Ret.fail());
            return;
        }

        // 文章关闭了评论的功能
        if (!article.isCommentEnable()) {
            renderJson(Ret.fail().set("message", "该文章的评论功能已关闭"));
            return;
        }

        //是否开启评论功能
        Boolean commentEnable = optionService.findAsBoolByKey("article_comment_enable");
        if (commentEnable == null || commentEnable == false) {
            renderJson(Ret.fail().set("message", "评论功能已关闭"));
            return;
        }

        User user = getLoginedUser();
        if (user == null){
            renderJson(Ret.fail().set("message", "用户未登录"));
            return;
        }
        //判断用户是否被冻结
        user = userService.findById(user.getId());
        if(!user.isStatusOk()){
            renderFailJson(1, "您的账号已被冻结!");
            return;
        }

        ArticleComment comment = new ArticleComment();

        comment.setArticleId(articleId);
        comment.setContent(content);
        comment.setPid(pid);
        comment.setEmail(user.getEmail());

        comment.setUserId(user.getId());
        comment.setAuthor(user.getNickname());

        comment.put("user", user.keepSafe());

        //是否是管理员必须审核
        Boolean reviewEnable = optionService.findAsBoolByKey("article_comment_review_enable");
        if (reviewEnable != null && reviewEnable == true) {
            comment.setStatus(ArticleComment.STATUS_UNAUDITED);
        }
        /**
         * 无需管理员审核、直接发布
         */
        else {
            comment.setStatus(ArticleComment.STATUS_NORMAL);
        }

        //记录文章的评论量
        articleService.doIncArticleCommentCount(articleId);

        if (pid != null) {
            //记录评论的回复数量
            commentService.doIncCommentReplyCount(pid);
        }
        commentService.saveOrUpdate(comment);

        Ret ret = Ret.ok();
        if (comment.isNormal()) {
            ret.set("comment", comment).set("code", 0);
        } else {
            ret.set("code", 0);
        }

        renderJson(ret);

        ArticleKit.doNotifyAdministrator(article, comment);
    }

    /**
     * 获取小程序banner
     */
    public void banners() {
        String type = getPara("type");
        List<Banner> banners;
        if(StrUtils.isBlank(type)){
            banners = bannerService.findListByType(Banner.TYPE_WECHAT_MINIPROGRAM);
        }else {
            banners = bannerService.findListByType(type);
        }

        renderJson(Ret.ok("categories", banners));
    }

    /**
     * 用户签到
     */
    public void userSign(){
        User user = getLoginedUser();
        if (user == null){
            renderJson(Ret.fail().set("message", "用户未登录"));
            return;
        }
        //判断用户是否被冻结
        user = userService.findById(user.getId());
        if(!user.isStatusOk()){
            renderFailJson(1, "您的账号已被冻结!");
            return;
        }
        String dateStr = DateFormatUtils.format(new Date(),"yyyy-MM-dd");

        UserSignLog userSignLog = userSignLogService.findUserSign(user.getId(),dateStr);
        if(userSignLog != null){
            renderFailJson("您今天已经签过到！");
            return;
        }
        userSignLog = new UserSignLog();
        userSignLog.setUserId(user.getId());
        userSignLog.setDateStr(dateStr);
        userSignLogService.save(userSignLog);
        renderOk();
    }


}
